package service

import (
	"strings"
	"time"
)
import (
	log "ac-common-go/glog"
	"ac-julink/cache"
	"ac-julink/manager"
	"ac-julink/tool/data"
	"ac-julink/tool/json"
	"ac-julink/tool/procinfo"
	"ac-julink/tool/sha256"
	"errors"
)

type messageInfo struct {
	messageId int
}

// 按照协议格式解析接收数据:HS{json}md5\r\n
// 解析101消息的wifiid信息,并处理TCP会话第一个消息为101认证消息
func HandelSessionData(input, _ip string, _fdid int, context *cache.SyncContext, client *manager.AcRestClient) (_wifiid, _msgResult string, _cryptType int, err error) {
	procinfo.AddCount(data.DEVICE_AUTHENTICATION)
	log.Infof("HandelSessionData======>>>%s", input)
	var _jsonBody string
	var _prekey string
	var _msgid int
	var cryptType int
	_jsonBody, _wifiid, _prekey, _msgid, err = PreProcessMsg(input, context, client)
	if err != nil {
		log.Errorf("Invalid data format ! ", err)
		return "", "", cryptType, err
	} else {
		//解析消息ID,判断是否为101认证消息
		if _msgid != data.DEVICE_AUTHENTICATION {
			log.Errorf("MsgId isn`t 101 !")
			err = errors.New("First msg is not 101 !")
			return "", "", cryptType, err
		} else {
			_msgResult, cryptType, err = HandleAuth(_jsonBody, _wifiid, _prekey, _ip, _fdid, context, client)
			if err != nil {
				log.Errorf("HandleAuth failed!%s,%+v", _wifiid, err)
				return "", "", cryptType, err
			}
		}
	}
	return _wifiid, _msgResult, cryptType, err
}

/*
接收消息预处理,包括:

	1.消息格式,长度验证
	2.数据分割
	3.token验证
	4.预制密钥获取
	5.MD5验证
*/
func PreProcessMsg(_msg string, context *cache.SyncContext, client *manager.AcRestClient) (_jsonBody, _wifiid, _prekey string, _msgid int, err error) {
	log.Infof("PreProcessMsg======>>>%s,%s", _wifiid, _jsonBody)
	//todo:AES256解密
	//common.AesDecrypt()
	//1.数据格式,长度校验
	msgType, err := CheckMsgFormat(_msg)
	if err != nil {
		log.Errorf("CheckMsgFormat failed:%s,%+v", _msg, err)
		err = errors.New("CLOSESESSION")
		return "", "", "", _msgid, err
	}
	if strings.Compare(msgType, "HEARTBEAT") == 0 {
		_jsonBody = _msg[2:len(_msg)]
		return _jsonBody, "", "", 902, nil
	}

	//2.数据格式分割,获取JSON和SHA256值(16位)
	msgJson, sha256_str := GetJsonSha256(_msg)
	log.Infof("JSON[%s]", msgJson)
	log.Infof("sha256_str[%s]", sha256_str)

	//解析消息ID
	_msgid, err = json.ParseMsgId(msgJson)
	if err != nil || _msgid == 0 {
		log.Errorf("ParseMsgId failed or invalid:%s,%s,%+v", _msg, _msgid, err)
		return "", "", "", _msgid, err
	}

	//3.Token验证(根据token获取wifiid).区分:101消息带wifiid字段,其它消息带token字段
	var wifiid string

	wifiid, err = CheckToken(msgJson, context, client)
	if err != nil {
		log.Errorf("CheckToken failed!%s, %+v", wifiid, err)
		err = errors.New("CLOSESESSION")
		return "", "", "", _msgid, err
	}
	var pre_key string

	if strings.Contains(strings.ReplaceAll(msgJson, " ", ""), "\"ProtVer\":\"HENC\"") {
		log.Infof("wifiid:%s is a HENC device", wifiid)
		if pre_key, err = client.GetPublicKey(wifiid, true, context); err != nil {
			log.Errorf("failed to fetch prekey for HENC wifiId %s", wifiid)
			return "", "", "", _msgid, err
		}
	} else {
		log.Infof("wifiid:%s is a common device", wifiid)
		if pre_key, err = client.GetPublicKey(wifiid, false, context); err != nil {
			log.Errorf("failed to fetch prekey for wifiId %s", wifiid)
			return "", "", "", _msgid, err
		}
	}

	log.Info("pre_key[%s]", pre_key)

	//5.sha256验证
	if !sha256.CheckSha256(pre_key+msgJson, sha256_str) {
		log.Errorf("sha256 check failed!%s,%s,%s,%+v", wifiid, pre_key, msgJson, err)
		err = errors.New("CLOSESESSION")
		return "", "", "", _msgid, err
	}
	return msgJson, wifiid, pre_key, _msgid, err
}

// 消息类型分发处理
func DispatchMessage(_msg, wifiId, ip string, fdid int, context *cache.SyncContext, client *manager.AcRestClient, cryptType int, time101 int64, sessionId int) (response string, err error) {
	log.Infof("DispatchMessage========>>>>>wifiId: %s, sessionId: %v, %s", wifiId, sessionId, _msg)
	timeStart := time.Now().UnixNano()
	var msgId int
	var msgJson string
	var wifiid string
	var prekey string

	msgJson, wifiid, prekey, msgId, err = PreProcessMsg(_msg, context, client)
	if err != nil {
		log.Error("PreProcessMsg failed !")
		return "", err
	}

	procinfo.AddCount(msgId)
	log.Infof("DispatchMessage[%d]", msgId)
	//分发消息
	switch msgId {
	case data.DEVICE_AUTHENTICATION: //101设备认证
		{
			log.Info("101 DEVICE_AUTHENTICATION")
			response, _, err = HandleAuth(msgJson, wifiid, prekey, ip, fdid, context, client)
		}
	case data.EXCHANGE_ENCRYPTION_KEY: //102密钥交换
		{
			log.Info("102 EXCHANGE_ENCRYPTION_KEY")
			response, err = HandleKey(msgJson, wifiid, prekey, context, client, cryptType)
		}
	case data.RETRIVE_SYSTEM_CONFIG: //103系统参数获取
		{
			log.Info("103 RETRIVE_SYSTEM_CONFIG")
			response, err = HandleSysConifg(wifiid, prekey, client, cryptType)
		}
	case data.SEND_CONTROL_COMMAND: //201控制指令结果返回
		{
			log.Info("201 SEND_CONTROL_COMMAND")
			err = HandleControlResult(msgJson, wifiid, prekey)
		}
	case data.SEND_QUERY_COMMAND: //202状态查询指令结果返回
		{
			log.Info("202 SEND_QUERY_COMMAND")
			err = HandleQueryCmd(msgJson, wifiid, prekey)
		}
	case data.SEND_CONTROL_RERET: //203状态重置指令
		{
			log.Info("203 SEND_CONTROL_RERET")
			err = HandleControlReset(msgJson, wifiid, prekey)
		}
	case data.QUERY_VERSON_COMMAND: //301版本查询结果返回
		{
			log.Info("301 QUERY_VERSON_COMMAND")
			err = HandleQueryVer(msgJson, wifiid)
		}
	case data.SEND_OTA_COMMAND: //302OTA升级结果返回
		{
			log.Info("302 SEND_OTA_COMMAND")
			err = HandleOtaResult(msgJson, wifiid)
		}
	case data.QUERY_OTA_COMMAND: //303OTA升级查询指令
		{
			log.Info("303 QUERY_OTA_COMMAND")
			response, err = HandleOtaQuery(msgJson, wifiid, prekey)
		}
	case data.SEND_MCU_UPGRADE_COMMAND: //305MCU升级结果返回
		{
			log.Info("305 SEND_MCU_UPGRADE_COMMAND")
			err = HandleMcuUpgradeResult(msgJson, wifiid)
		}
	case data.SEND_COMMON_COMMAND: //310 aFOTA设备固件信息下发反馈，使用通用数据上传
		{
			log.Info("310 SEND_COMMON_COMMAND")
			err = HandelCommonDataResult(msgJson, wifiid, msgId)
		}
	case data.REPORT_COMMON_COMMAND: //312 aFOTA升级结果反馈，使用通用数据上传
		{
			log.Info("312 REPORT_COMMON_COMMAND")
			err = HandelCommonDataResult(msgJson, wifiid, msgId)
		}
	case data.BIND_DEV_COMMAND: //401设备绑定指令
		{
			log.Info("401 BIND_DEV_COMMAND")
			response, err = HandleDevBind(msgJson, wifiid, prekey)
		}
	case data.UNBIND_DEV_COMMAND: //402设备解绑指令
		{
			log.Info("402 UNBIND_DEV_COMMAND")
			response, err = HandleDevUnBind(msgJson, wifiid, prekey)
		}
	//case data.GET_BIND_DEV_COMMAND: //403获取绑定设备列表
	//	{
	//		log.Info("403 GET_BIND_DEV_COMMAND")
	//		response, err = HandleBindDevList(wifiid, prekey)
	//	}
	//case data.GET_HOME_DEVLIST_COMMAND: //404获取网关所属家庭下设备列表
	//	{
	//		log.Info("404 GET_HOME_DEVLIST_COMMAND")
	//		response, err = HandleHomeDevList(wifiid, prekey)
	//	}
	case data.DEVICE_EXTINFO_STORE: //406设备扩展信息存储
		{
			log.Info("406 DEVICE_EXTINFO_STORE")
			response, err = HandleDevExtInfoStore(msgJson, wifiid, prekey)
		}
	case data.DEVICE_RESET: //407设备重置
		{
			log.Info("407 DEVICE_RESET")
			response, err = HandelDevReset(msgJson, wifiid, prekey)
		}
	//case data.GET_SCENE_LIST_COMMAND: //501获取网关所在家庭的场景信息列表
	//	{
	//		log.Info("501 GET_SCENE_LIST_COMMAND")
	//		response, err = HandelGetSceneList(wifiid, prekey)
	//	}
	//case data.GET_SCENE_INFO_COMMAND: //502获取场景信息
	//	{
	//		log.Info("502 GET_SCENE_INFO_COMMAND")
	//		response, err = HandelGetSceneInfo(msgJson, wifiid, prekey)
	//	}
	case data.SEND_CONFIG_DATA_COMMAND: //601配置数据上传
		{
			log.Info("601 SEND_CONFIG_DATA_COMMAND")
			err = HandelConfigDataResult(msgJson, wifiid)
		}
	case data.REPORT_CONFIG_DATA: //602配置数据上传
		{
			log.Info("602 REPORT_CONFIG_DATA")
			err = HandelConfigDataReport(msgJson, wifiid)
		}
	case data.REPORT_STATUS_COMMAND: //901设备状态上报
		{
			log.Info("901 REPORT_STATUS_COMMAND")
			err = HandleReportStatus(msgJson, wifiid, prekey)
		}
	case data.REPORT_HEARTBEAT_COMMAND: //902设备心跳
		{
			log.Info("902 REPORT_HEARTBEAT_COMMAND")
			response, err = HandleHeartBeatReport(wifiId, ip, fdid, context, client, cryptType, time101)
		}
	case data.REPORT_STATUS_UPDATE: //903设备上报
		{
			log.Info("903 REPORT_STATUS_UPDATE")
			response, err = HandleReportUpdateStatus(msgJson, wifiid, prekey)
		}
	default:
		log.Error("Invaild msgId !")
		err = errors.New("Invaild msgId !")
	}
	log.Infof("DispatchMessage response[%s] to wifiId:[%s] for record:[%d], [%+v]", response, wifiId, msgId, err)
	log.Warningf("RECORD:%d,%s,%d,%dms,err:%+v", msgId, wifiId, sessionId, (time.Now().UnixNano()-timeStart)/1e6, err)
	return response, err
}
